1
//--------------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // File: ObservableConcurrentDictionary.cs
7 //--------------------------------------------------------------------------
9 using System
.Collections
.Generic
;
10 using System
.Collections
.Specialized
;
11 using System
.ComponentModel
;
12 using System
.Threading
;
13 using System
.Diagnostics
;
15 namespace System
.Collections
.Concurrent
18 /// Provides a thread-safe dictionary for use with data binding.
20 /// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam>
21 /// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam>
22 [DebuggerDisplay("Count={Count}")]
23 public class ObservableConcurrentDictionary
<TKey
, TValue
> :
24 ICollection
<KeyValuePair
<TKey
, TValue
>>, IDictionary
<TKey
, TValue
>,
25 INotifyCollectionChanged
, INotifyPropertyChanged
27 private readonly SynchronizationContext _context
;
28 private readonly ConcurrentDictionary
<TKey
, TValue
> _dictionary
;
31 /// Initializes an instance of the ObservableConcurrentDictionary class.
33 public ObservableConcurrentDictionary()
35 _context
= AsyncOperationManager
.SynchronizationContext
;
36 _dictionary
= new ConcurrentDictionary
<TKey
, TValue
>();
39 /// <summary>Event raised when the collection changes.</summary>
40 public event NotifyCollectionChangedEventHandler CollectionChanged
;
41 /// <summary>Event raised when a property on the collection changes.</summary>
42 public event PropertyChangedEventHandler PropertyChanged
;
45 /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary.
47 private void NotifyObserversOfChange()
49 var collectionHandler
= CollectionChanged
;
50 var propertyHandler
= PropertyChanged
;
51 if (collectionHandler
!= null || propertyHandler
!= null)
55 if (collectionHandler
!= null)
57 collectionHandler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction
.Reset
));
59 if (propertyHandler
!= null)
61 propertyHandler(this, new PropertyChangedEventArgs("Count"));
62 propertyHandler(this, new PropertyChangedEventArgs("Keys"));
63 propertyHandler(this, new PropertyChangedEventArgs("Values"));
69 /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
70 /// <param name="item">The item to be added.</param>
71 /// <returns>Whether the add was successful.</returns>
72 private bool TryAddWithNotification(KeyValuePair
<TKey
, TValue
> item
)
74 return TryAddWithNotification(item
.Key
, item
.Value
);
77 /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
78 /// <param name="key">The key of the item to be added.</param>
79 /// <param name="value">The value of the item to be added.</param>
80 /// <returns>Whether the add was successful.</returns>
81 private bool TryAddWithNotification(TKey key
, TValue
value)
83 bool result
= _dictionary
.TryAdd(key
, value);
84 if (result
) NotifyObserversOfChange();
88 /// <summary>Attempts to remove an item from the dictionary, notifying observers of any changes.</summary>
89 /// <param name="key">The key of the item to be removed.</param>
90 /// <param name="value">The value of the item removed.</param>
91 /// <returns>Whether the removal was successful.</returns>
92 private bool TryRemoveWithNotification(TKey key
, out TValue
value)
94 bool result
= _dictionary
.TryRemove(key
, out value);
95 if (result
) NotifyObserversOfChange();
99 /// <summary>Attempts to add or update an item in the dictionary, notifying observers of any changes.</summary>
100 /// <param name="key">The key of the item to be updated.</param>
101 /// <param name="value">The new value to set for the item.</param>
102 /// <returns>Whether the update was successful.</returns>
103 private void UpdateWithNotification(TKey key
, TValue
value)
105 _dictionary
[key
] = value;
106 NotifyObserversOfChange();
109 #region ICollection<KeyValuePair<TKey,TValue>> Members
110 void ICollection
<KeyValuePair
<TKey
, TValue
>>.Add(KeyValuePair
<TKey
, TValue
> item
)
112 TryAddWithNotification(item
);
115 void ICollection
<KeyValuePair
<TKey
, TValue
>>.Clear()
117 ((ICollection
<KeyValuePair
<TKey
, TValue
>>)_dictionary
).Clear();
118 NotifyObserversOfChange();
121 bool ICollection
<KeyValuePair
<TKey
, TValue
>>.Contains(KeyValuePair
<TKey
, TValue
> item
)
123 return ((ICollection
<KeyValuePair
<TKey
, TValue
>>)_dictionary
).Contains(item
);
126 void ICollection
<KeyValuePair
<TKey
, TValue
>>.CopyTo(KeyValuePair
<TKey
, TValue
>[] array
, int arrayIndex
)
128 ((ICollection
<KeyValuePair
<TKey
, TValue
>>)_dictionary
).CopyTo(array
, arrayIndex
);
131 int ICollection
<KeyValuePair
<TKey
, TValue
>>.Count
133 get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Count; }
136 bool ICollection
<KeyValuePair
<TKey
, TValue
>>.IsReadOnly
138 get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly; }
141 bool ICollection
<KeyValuePair
<TKey
, TValue
>>.Remove(KeyValuePair
<TKey
, TValue
> item
)
144 return TryRemoveWithNotification(item
.Key
, out temp
);
148 #region IEnumerable<KeyValuePair<TKey,TValue>> Members
149 IEnumerator
<KeyValuePair
<TKey
, TValue
>> IEnumerable
<KeyValuePair
<TKey
, TValue
>>.GetEnumerator()
151 return ((ICollection
<KeyValuePair
<TKey
, TValue
>>)_dictionary
).GetEnumerator();
154 IEnumerator IEnumerable
.GetEnumerator()
156 return ((ICollection
<KeyValuePair
<TKey
, TValue
>>)_dictionary
).GetEnumerator();
160 #region IDictionary<TKey,TValue> Members
161 public void Add(TKey key
, TValue
value)
163 TryAddWithNotification(key
, value);
166 public bool ContainsKey(TKey key
)
168 return _dictionary
.ContainsKey(key
);
171 public ICollection
<TKey
> Keys
173 get { return _dictionary.Keys; }
176 public bool Remove(TKey key
)
179 return TryRemoveWithNotification(key
, out temp
);
182 public bool TryGetValue(TKey key
, out TValue
value)
184 return _dictionary
.TryGetValue(key
, out value);
187 public ICollection
<TValue
> Values
189 get { return _dictionary.Values; }
192 public TValue
this[TKey key
]
194 get { return _dictionary[key]; }
195 set { UpdateWithNotification(key, value); }